package com.controller.lib

import android.app.Service
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.text.TextUtils
import android.util.Log
import androidx.annotation.RequiresApi
import com.controller.lib.DmSdk
import com.controller.lib.download.OKDownloadHelper
import com.controller.lib.entity.Ap
import com.controller.lib.entity.CommandCallbackEntity
import com.controller.lib.entity.CommandValueEntity
import com.controller.lib.entity.UpdateDeviceEntity
import com.controller.lib.net.ApiService
import com.controller.lib.net.RetrofitClient
import com.controller.lib.utils.SystemUtils
import com.google.gson.Gson
import com.hivemq.client.mqtt.MqttClient
import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient
import com.hivemq.client.mqtt.mqtt3.exceptions.Mqtt3ConnAckException
import com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAckReturnCode
import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.json.JSONObject
import timber.log.Timber
import java.util.concurrent.TimeUnit
import kotlin.text.Charsets
data class MqttMessageEntity(
  val appId: Int,
  val type: String,
  val value: ValueEntity
)

data class ValueEntity(
  val commandType: String,
  val commandValue: String,
  val commandID: String
)
object Constants {
  //设置系统音量
  const val SET_VOLUME = "SetVolume"

  //设置背景壁纸
  const val SET_SYS_BACKGROUND = "SetSysBackground"

  //下载文件消息
  const val SET_DOWNLOAD_FILE = "SetDownloadFile"

  //升级应用
  const val SET_UPGRADE_APP = "SetUpgradeApp"

  //设置关机
  const val SET_SHUT_DOWN = "SetShutDown"

  //设置开机
  const val STARTS_UP_DEVICE = "StartsUpDevice"

  //重启
  const val SET_RESTART = "SetRestart"

  //节能模式
  const val SET_ENERGY_SAVE = "SetEnergySave"

  //自定义消息
  const val CUSTOM_DIRECTIVE = "CustomDirective"

  //视频消息
  const val SET_DISTRIBUTE_VIDEOS = "video"
}

class BootRequestService : Service() {
  private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
  private val apiService = RetrofitClient.createService<ApiService>()
  private var mqttClient: Mqtt3AsyncClient? = null
  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// 发起请求
    serviceScope.launch {
      queryDeviceMqttMessage()
    }
    return START_NOT_STICKY
  }

  override fun onBind(intent: Intent?): IBinder? = null

  override fun onDestroy() {
    super.onDestroy()
    mqttClient?.disconnect()
    serviceScope.cancel()
  }

  @RequiresApi(Build.VERSION_CODES.N)
  private fun connectMqtt(ap: Ap,id:Int) {
    // Disconnect and release the old client instance if it exists
    mqttClient?.disconnect()
    mqttClient = MqttClient.builder()
      .identifier(ap.topic)
      .serverHost(ap.address)
      .serverPort(1883)
      .useMqttVersion3()
      .addConnectedListener {
        Log.i("BootRequestService", "MQTT (re)connected.")
      }
      .addDisconnectedListener { context ->
        Log.w("BootRequestService", "MQTT disconnected. Cause: ${context.cause.message}", context.cause)
        val cause = context.cause
        if (cause is Mqtt3ConnAckException && cause.mqttMessage.returnCode == Mqtt3ConnAckReturnCode.BAD_USER_NAME_OR_PASSWORD) {
          Log.e("BootRequestService", "MQTT Auth failed. Stopping client and re-fetching credentials.")
          serviceScope.launch {
            // Important: capture the client that triggered this event
            val clientToDisconnect = mqttClient
            // Nullify the reference in the service so we don't try to use it elsewhere
            mqttClient = null
            // Disconnect the actual client instance
            clientToDisconnect?.disconnect()

            // Wait a bit before retrying to avoid a tight loop
            delay(10_000)
            queryDeviceMqttMessage()
          }
        }
      }
      .automaticReconnect()
      .initialDelay(5, TimeUnit.SECONDS)
      .maxDelay(10 * 60, TimeUnit.SECONDS)
      .applyAutomaticReconnect()
      .buildAsync()

    mqttClient!!.connectWith()
      .simpleAuth()
      .username(ap.accessKey)
      .password(ap.secretKey.toByteArray(Charsets.UTF_8))
      .applySimpleAuth()
      .send()
      .whenComplete { _, throwable ->
        if (throwable != null) {
          Log.e("BootRequestService", "MQTT连接失败", throwable)
        } else {
          Log.d("BootRequestService", "MQTT连接成功")
          mqttClient!!.subscribeWith()
            .topicFilter(ap.topic)
            .qos(com.hivemq.client.mqtt.datatypes.MqttQos.AT_LEAST_ONCE)
            .callback { publish: Mqtt3Publish ->
              val msg = publish.payload
                .map { buffer ->
                  val bytes = ByteArray(buffer.remaining())
                  buffer.get(bytes)
                  String(bytes)
                }
                .orElse("")
              Log.d("BootRequestService", "收到MQTT消息: $msg")
              try {
                val json = JSONObject(msg)
                val valueJson = json.getJSONObject("value")
                val entity = MqttMessageEntity(
                  appId = json.getInt("appId"),
                  type = json.getString("type"),
                  value = ValueEntity(
                    commandType = valueJson.getString("commandType"),
                    commandValue = valueJson.getString("commandValue"),
                    commandID = valueJson.getString("commandID")
                  )
                )
                Log.d("BootRequestService", "已转为对象: $entity")
                dispatchMqttMessage(entity,id)
              } catch (e: Exception) {
                Log.e("BootRequestService", "消息解析失败", e)
              }
            }
            .send()
            .whenComplete { _, subThrowable ->
              if (subThrowable != null) {
                Log.e("BootRequestService", "订阅主题失败", subThrowable)
              } else {
                Log.d("BootRequestService", "已订阅主题: $ap.topic")
              }
            }
        }
      }
  }

  private fun dispatchMqttMessage(entity: MqttMessageEntity,id:Int) {
    val valueEntity = entity.value
    when (valueEntity.commandType) {
      Constants.SET_VOLUME -> {
        //调节音量值
        //entity.value.commandValue
        ControllerHelper.instance.setStreamVolume(Integer.parseInt(valueEntity.commandValue))
      }

      Constants.SET_SYS_BACKGROUND -> {
        //图片下载地址 下载图片并设置为背景
        val commandValueEntity = getCommandValueEntity(valueEntity.commandValue)
        ControllerHelper.instance.showPictures(commandValueEntity.fileUrl,commandValueEntity.md5)
      }

      Constants.SET_DOWNLOAD_FILE -> {
        //下载文件，文件的下载地址
        val commandValueEntity = getCommandValueEntity(valueEntity.commandValue)
        ControllerHelper.instance.downLoaderFile(commandValueEntity.fileUrl,commandValueEntity.md5)
      }

      Constants.CUSTOM_DIRECTIVE -> {
        // 优先回调宿主监听
        DmSdk.notifyCustomDirective(valueEntity.commandValue,Constants.CUSTOM_DIRECTIVE)
        // 兼容原有逻辑，继续发广播
        ControllerHelper.instance.sendSystemCommands(valueEntity.commandValue)
      }

      Constants.SET_UPGRADE_APP -> {
        val commandValueEntity = getCommandValueEntity(valueEntity.commandValue)
        ControllerHelper.instance.upgradeApk(commandValueEntity.fileUrl,commandValueEntity.md5)
      }

      Constants.SET_SHUT_DOWN -> {
        //关机
        DmSdk.notifyCustomDirective("",Constants.SET_SHUT_DOWN)
      }

      Constants.SET_RESTART -> {
        //重启
        DmSdk.notifyCustomDirective("",Constants.SET_RESTART)
      }

      Constants.SET_DISTRIBUTE_VIDEOS -> {
        val commandValueEntity = getCommandValueEntity(valueEntity.commandValue)
        ControllerHelper.instance.playerVideo(commandValueEntity.fileUrl,commandValueEntity.md5)
      }

      else -> {
        Timber.w("未知的指令类型: ${valueEntity.commandType}")
      }
    }
    reportCallbackCommand(valueEntity.commandID,id)
  }

  /**
   * 上报mqtt的执行结果
   * */
  fun reportCallbackCommand(commandID: String,appId:Int) {
    try {
//      val sn = ControllerHelper.instance.getDeviceSN()
      Timber.d("BootRequestService: 上报执行结果, commandID: $commandID, appId: $appId")
      val response = apiService.commandCallback(CommandCallbackEntity(commandID, appId)).execute()
      if (response.isSuccessful) {
        val result = response.body()
        Timber.d("BootRequestService: 上报执行结果: %s,%s", result?.code == 0, result)
      } else {
        Timber.e("BootRequestService: 上报执行结果失败: ${response.errorBody()?.string()}")
      }
    } catch (e: Exception) {
      // 处理网络异常
      Timber.e("BootRequestService: 上报执行结果异常: ${e.printStackTrace()}")
    }
  }

  /**
   * 查询设备mqtt连接信息
   * */
  fun queryDeviceMqttMessage() {
    try {
//      val sn = DmSdk.getSn()
      val macAddress =DmSdk.getMacAddress()
      Timber.d("BootRequestService: 查询设备mqtt连接信息 MAC: $macAddress")
      val response = apiService.getDeviceMqttMessage(macAddress.toString()).execute()
      if (response.isSuccessful) {
        val apResult = response.body()?.result
        val ap = apResult?.ap
        if (ap != null) {
          connectMqtt(ap,apResult?.device?.id ?: 0)
        }
        updateDeviceType(apResult?.device?.id.toString())
      } else {
        Timber.e("BootRequestService: 获取mqtt连接信息失败: ${response.errorBody()?.string()}")
      }
    } catch (e: Exception) {
      // TODO 处理网络异常,是否重试
      Timber.e("BootRequestService: 获取mqtt连接信息异常: ${e.printStackTrace()}")
      stopSelf()
    }
  }

  /**
   * 更新设备类型
   * */
  private fun updateDeviceType(deviceId: String) {
    try {
      val macAddress = DmSdk.getMacAddress()
      val version = SystemUtils.getVersionCode(DmSdk.getContext())
      val equipmentType = SystemUtils.getDeviceModel()
      val equipmentVersion = SystemUtils.getDisplayId()
//      val deviceSerialNo = DmSdk.getSn()
      Timber.d("BootRequestService: 更新设备类型,设备ID: $deviceId, mac: $macAddress, version: $version, equipmentType: $equipmentType, equipmentVersion: $equipmentVersion")
      val response =
        apiService.updateDeviceMessage(
          deviceId,
          UpdateDeviceEntity("panel", macAddress.toString() , version.toString(),equipmentType, equipmentVersion)
        ).execute()
      if (response.isSuccessful) {
        val result = response.body()
        Timber.d("BootRequestService: 更新设备类型成功: $result")
        checkAppUpgrade()
      } else {
        Timber.e("BootRequestService: 更新设备类信息失败: ${response.errorBody()?.string()}")
      }
    } catch (e: Exception) {
      // 处理网络异常
      Timber.e("BootRequestService: 更新设备类信息异常: ${e.printStackTrace()}")
    }
  }

  /**
   * 检查是否需要升级
   * */
  private fun checkAppUpgrade() {
    Timber.d("BootRequestService: 检查应用升级")
//    val sn = DmSdk.getSn()
    val macAddress = ControllerHelper.instance.getMacAddress()
    Timber.d("BootRequestService: 检查应用升级, MAC: $macAddress")
    val response = apiService.checkDeviceUpdateVersion(macAddress).execute()
    if (response.isSuccessful) {
      val result = response.body()?.result
      Timber.d("checkAppUpgrade: 检查升级结果: $result")
      val version = SystemUtils.getVersionCode(DmSdk.getContext())
      val fileUrl = result?.fileUrl
      if (!TextUtils.isEmpty(fileUrl) && fileUrl?.contains(".apk") == true&&version!=result.version.toInt()) {
       // ControllerHelper.instance.upgradeApk(result.fileUrl, result.md5)
      }
    }
  }

  private fun getCommandValueEntity(commandValue:String):CommandValueEntity{
    val json = JSONObject(commandValue)
    val entity = CommandValueEntity(
      fileUrl = json.getString("fileUrl"),
      md5 = json.getString("MD5")
    )
    Timber.d("BootRequestService: 解析CommandValueEntity: $entity")
    return entity
  }
}